﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Web.UI.WebControls;
using System.Web.UI;
using System.Diagnostics;
using System.ComponentModel;
using System.Drawing.Design;
using Axe.Extensions;
using System.Reflection;
using System.IO;
using System.Security.Permissions;
using System.Web;
using System.Web.SessionState;

namespace Axe.Web.Controls
{
    [AspNetHostingPermission(SecurityAction.InheritanceDemand, Level=AspNetHostingPermissionLevel.Minimal)]
    [AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)]
    public class ServerValidateEventArgsExt : ServerValidateEventArgs
    {
        public string ErrorMessage {get;set;}

        public ServerValidateEventArgsExt(ServerValidateEventArgs a)
            : base(a.Value, a.IsValid)
        {
        }

        public ServerValidateEventArgsExt(string value, bool valid)
            : base(value,valid)
        {
        }
    }

    public class CallbackServerValidator : CustomValidator, ICallbackEventHandler
    {
        #region private void EmbedScriptCode()
        [ReflectionPermission(SecurityAction.InheritanceDemand, MemberAccess = true)]
        [ReflectionPermission(SecurityAction.Demand, MemberAccess = true)]
        private void EmbedScriptCode()
        {
            // Hack to get theFormPostData
            Page.ClientScript.GetCallbackEventReference(this, null, null, null);
         
            Assembly dll = Assembly.GetCallingAssembly();
            string jsCode = null;

            Stream s = dll.GetManifestResourceStream(typeof(CallbackServerValidator), "CallbackServerValidator.js");
            using (StreamReader reader = new StreamReader(s))
            {
                jsCode = reader.ReadToEnd();
            }


            if (!Page.ClientScript.IsClientScriptBlockRegistered("CallbackServerValidator"))
            {
                Page.ClientScript.RegisterClientScriptBlock(typeof(CallbackServerValidator), "CallbackServerValidator", jsCode, true);
            }
        } 
        #endregion

        protected override void OnPreRender(EventArgs e)
        {
            EmbedScriptCode();
            
            string jsCode = null;

            Assembly dll = Assembly.GetExecutingAssembly();

            Stream s = dll.GetManifestResourceStream(typeof(CallbackServerValidator), "ValidatorFunctionStub.js");
            using (StreamReader reader = new StreamReader(s))
            {
                jsCode = reader.ReadToEnd();
            }

            string imageUrl = ResolveClientUrl(ValidationProgressImage);
            string CallbackName = this.ClientID + "_Function";
            string Script = String.Format(jsCode, 
                    CallbackName,
                    this.ClientID,
                    this.UniqueID);

            Page.ClientScript.RegisterClientScriptBlock(typeof(CallbackServerValidator), ClientID, Script, true);
            ClientValidationFunction = CallbackName;

            base.OnPreRender(e);
        }

        #region public new string ClientValidationFunction
        [Browsable(false)]
        public new string ClientValidationFunction
        {
            get { return base.ClientValidationFunction; }
            protected set { base.ClientValidationFunction = value; }
        } 
        #endregion

        #region public string ValidationProgressImage
        [Category("Apperance")]
        [DefaultValue("ValidationProgressImage")]
        [UrlProperty, Editor("System.Web.UI.Design.ImageUrlEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor))]
        public string ValidationProgressImage
        {
            get { return ViewState.Get<string>("ValidationProgressImage", ""); }
            set { ViewState["ValidationProgressImage"] = value; }
        }
        #endregion

        #region public bool EnableServerErrorMessage
        [DefaultValue(false), Category("Behavior")]
        public virtual bool EnableServerErrorMessage
        {
            get { return ViewState.Get<bool>("EnableServerErrorMessage", false); }
            set { ViewState["EnableServerErrorMessage"] = value; }
        } 
        #endregion

        #region ICallbackEventHandler Members

        KeyValuePair<bool,string> ValRes;

        public string GetCallbackResult()
        {
            string result = ValRes.Key.ToString().ToLower();

            if (EnableServerErrorMessage)
            {
                result += "|" + ValRes.Value;
            }

            return result;
        }

        public void RaiseCallbackEvent(string eventArgument)
        {
            ValRes = OnServerValidateExt(eventArgument);
        }

        #endregion

        public new event EventHandler<ServerValidateEventArgsExt> ServerValidate;

        #region protected virtual KeyValuePair<bool, string> OnServerValidateExt(string value)
        protected virtual KeyValuePair<bool, string> OnServerValidateExt(string value)
        {
            if (ServerValidate != null)
            {
                ServerValidateEventArgsExt args = new ServerValidateEventArgsExt(value, true);
                ServerValidate(this, args);
                return new KeyValuePair<bool, string>(args.IsValid, args.ErrorMessage);
            }

            return new KeyValuePair<bool, string>(true, String.Empty);
        } 
        #endregion

        #region protected override bool OnServerValidate(string value)
        protected override bool OnServerValidate(string value)
        {
            return OnServerValidateExt(value).Key;
        } 
        #endregion
    }
}
